
using Abp.Application.Services.Dto;
using Abp.Authorization;
using Abp.Authorization.Users;
using Abp.AutoMapper;
using Abp.Domain.Entities.Auditing;
using Abp.Domain.Repositories;
using Abp.Extensions;
using Abp.Linq.Extensions;
using Abp.UI;
using Abp.Web.Models;
using L._52ABP.Application.Dtos;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Net.Http.Headers;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using Yozeev.Authorization;
using Yozeev.BusinessLogic.Authorization;
using Yozeev.BusinessLogic.BoatBasic.ExcelDto;
using Yozeev.BusinessLogic.Common.Dtos;
using Yozeev.BusinessLogic.Common.ExcelDto;
using Yozeev.BusinessLogic.DomainService;
using Yozeev.BusinessLogic.Dtos;
using Yozeev.Common;
using Yozeev.IO.ExcelHelper;
using Yozeev.UserManagement.Users.Exporting;

namespace Yozeev.BusinessLogic
{
	/// <summary>
	/// Customer应用层服务的接口实现方法  
	///</summary>
	[AbpAuthorize]
	public class CustomerAppService : YozeevAppServiceBase, ICustomerAppService
    {
        private readonly IRepository<Customer, Guid> _entityRepository;

		private readonly IRepository<RechargeRecord, Guid> _RechargeRecordRepository;

		private readonly ICustomerManager _entityManager;

		private readonly IExcelHelper _excelHelper;

		private readonly IQueryHelper _queryHelper;

		private readonly ICustomListExcelExporter _customListExcelExporter;

		private readonly IHostingEnvironment _hostingEnvironment;

		private readonly IEnumerable<IPasswordValidator<Customer>> _passwordValidators;

		private readonly IPasswordHasher<Customer> _passwordHasher;

		private readonly CustomerManager _customerManager;

		/// <summary>
		/// 构造函数 
		///</summary>
		public CustomerAppService(
		IRepository<Customer, Guid> entityRepository
		, ICustomerManager entityManager
			, IExcelHelper excelHelper
			, ICustomListExcelExporter customListExcelExporter
			, IHostingEnvironment hostingEnvironment
			, IQueryHelper queryHelper
			, CustomerManager customerManager
			, IRepository<RechargeRecord, Guid> RechargeRecordRepository
		)
		{
			_entityRepository = entityRepository;
			_entityManager = entityManager;
			_excelHelper = excelHelper;
			_customListExcelExporter = customListExcelExporter;
			_hostingEnvironment = hostingEnvironment;
			_queryHelper = queryHelper;
			_customerManager = customerManager;
			_RechargeRecordRepository = RechargeRecordRepository;
		}

        /// <summary>
        /// 获取Customer的分页列表信息
        ///</summary>
        /// <param name="input"></param>
        /// <returns></returns>
		[HttpPost]
        public async Task<PagedResultDto<CustomerListDto>> GetPaged(GetCustomersInput input)
		{
			var expression = _queryHelper.WhereExp<Customer>(input.queryData);
			if (AbpUserBase.AdminUserName != GetCurrentUser().UserName)
				expression = _queryHelper.SetWhereExp<Customer>(expression, GetViewTypeEnum<Customer>(),await GetBranchUser());
			var query = _entityRepository.GetAll().Where(expression);
			// TODO:根据传入的参数添加过滤条件
            

			var count = await query.CountAsync();

			var entityList = await query
					.OrderBy(input.Sorting).AsNoTracking()
					.PageBy(input)
					.ToListAsync();

			// var entityListDtos = ObjectMapper.Map<List<CustomerListDto>>(entityList);
			var entityListDtos =entityList.MapTo<List<CustomerListDto>>();

			return new PagedResultDto<CustomerListDto>(count,entityListDtos);

		}

		///// <summary>
		///// 获取Customer的分页列表信息--post
		/////</summary>
		///// <param name="input"></param>
		///// <returns></returns>
		//public async Task<PagedResultDto<CustomerListDto>> GetPagedForPost(GetCustomersInput input)
		//{
		//	var expression = _queryHelper.WhereExp<Customer>(input.queryData);
		//	var query = _entityRepository.GetAll().Where(expression).Select(g=> new Customer { 
		//		CustomerName=g.CustomerName,
		//		Mobile=g.Mobile,
		//		Photo=g.Photo,
		//		Sex=g.Sex,
		//		LoginPwd=g.LoginPwd,
		//		Country=g.Country,
		//		Province=g.Province,
		//		City=g.City,
		//		County=g.County,
		//		CertificatesNum=g.CertificatesNum,
		//		OpenID=g.OpenID,
		//		DateOfBirth=g.DateOfBirth,
		//		CreationTime=g.CreationTime,
		//		CreatorUserId=g.CreatorUserId,
		//		VerifiableType =g.VerifiableType,
		//	});
		//	// TODO:根据传入的参数添加过滤条件


		//	var count = await query.CountAsync();

		//	var entityList = await query
		//			.OrderBy(input.Sorting).AsNoTracking()
		//			.PageBy(input)
		//			.ToListAsync();

		//	// var entityListDtos = ObjectMapper.Map<List<CustomerListDto>>(entityList);
		//	var entityListDtos = entityList.MapTo<List<CustomerListDto>>();

		//	return new PagedResultDto<CustomerListDto>(count, entityListDtos);

		//}
		/// <summary>
		/// 通过指定id获取CustomerListDto信息
		/// </summary>
		public async Task<CustomerListDto> GetById(EntityDto<Guid> input)
		{
			var entity = await _entityRepository.GetAsync(input.Id);

		    return entity.MapTo<CustomerListDto>();
		}

		/// <summary>
		/// 获取编辑 Customer
		/// </summary>
		/// <param name="input"></param>
		/// <returns></returns>
		public async Task<GetCustomerForEditOutput> GetForEdit(NullableIdDto<Guid> input)
		{
			var output = new GetCustomerForEditOutput();
			CustomerEditDto editDto;

			if (input.Id.HasValue)
			{
				var entity = await _entityRepository.GetAsync(input.Id.Value);

				editDto = entity.MapTo<CustomerEditDto>();

				//customerEditDto = ObjectMapper.Map<List<customerEditDto>>(entity);
			}
			else
			{
				editDto = new CustomerEditDto();
			}

			output.Customer = editDto;
			return output;
		}

		/// <summary>
		/// 添加或者修改Customer的公共方法
		/// </summary>
		/// <param name="input"></param>
		/// <returns></returns>
		public async Task CreateOrUpdate(CreateOrUpdateCustomerInput input)
        {
			input.Customer.SetTime();
			if (input.Customer.Id.HasValue)
			{
				await Update(input.Customer);
			}
			else
			{
				await Create(input.Customer);
			}
		}
		/// <summary>
		/// 添加Customer的公共方法,带有返回值
		/// </summary>
		/// <param name="input"></param>
		/// <returns></returns>
		public async Task<CustomerExistsDto> CreateOrUpdateReturn(CreateOrUpdateCustomerInput input)
		{
			CustomerExistsDto customerExistsDto = new CustomerExistsDto()
			{
				Exist = true,
				Customer = input.Customer,
			};
			Customer customer = await _entityManager.GetByIdentityNo(input.Customer.CertificatesNum);
			if(customer!=null)
			{
				if (customer.CustomerName != input.Customer.CustomerName)
				{
					switch (input.operation)
					{
						case "0":
							{
								throw new UserFriendlyException("请确认用户名:" + input.Customer.CustomerName + "和证件号:" + input.Customer.CertificatesNum + "是否正确");
							}
						case "1":
							{
								customer.CustomerName = input.Customer.CustomerName;
								customer.Mobile = input.Customer.Mobile;
								customer.Sex = input.Customer.Sex;
								customer = await _entityRepository.UpdateAsync(customer);
							}
							break;
						case "2": break;
					}
				}
				customerExistsDto.Customer = customer.MapTo<CustomerEditDto>();
			}else
			{
				input.Customer.SetTime();
				customerExistsDto.Customer = await Create(input.Customer);
				customerExistsDto.Exist = false;
			}
			return customerExistsDto;
		}
		/// <summary>
		/// 新增Customer
		/// </summary>
		protected virtual async Task<CustomerEditDto> Create(CustomerEditDto input)
		{
			//TODO:新增前的逻辑判断，是否允许新增

            // var entity = ObjectMapper.Map <Customer>(input);
            var entity=input.MapTo<Customer>();
			

			entity = await _entityRepository.InsertAsync(entity);
			return entity.MapTo<CustomerEditDto>();
		}

		/// <summary>
		/// 编辑Customer
		/// </summary>
		protected virtual async Task Update(CustomerEditDto input)
		{
			//TODO:更新前的逻辑判断，是否允许更新

			var entity = await _entityRepository.GetAsync(input.Id.Value);
			input.MapTo(entity);

			// ObjectMapper.Map(input, entity);
		    await _entityRepository.UpdateAsync(entity);
		}

		/// <summary>
		/// 删除Customer信息的方法
		/// </summary>
		/// <param name="input"></param>
		/// <returns></returns>
		public async Task Delete(EntityDto<Guid> input)
		{
			//TODO:删除前的逻辑判断，是否允许删除
			await _entityRepository.DeleteAsync(input.Id);
		}

		/// <summary>
		/// 批量删除Customer的方法
		/// </summary>
		public async Task BatchDelete(List<Guid> input)
		{
			// TODO:批量删除前的逻辑判断，是否允许删除
			await _entityRepository.DeleteAsync(s => input.Contains(s.Id));
		}

		/// <summary>
		/// 根据证件ID查询客户，如果客户存在，则返回客户信息
		/// </summary>
		/// <param name="identity"></param>
		/// <returns></returns>
        public async Task<CustomerExistsDto> Exists(string identity)
        {
            var output = new CustomerExistsDto();

			Customer customer = await _entityManager.GetByIdentityNo(identity);
            output.Customer = customer.MapTo<CustomerEditDto>();

			if (output.Customer != null)
            {
                output.Exist = true;
            }

            return output;
        }

		/// <summary>
		/// 上传客户照片
		/// </summary>
		/// <param name="file"></param>
		/// <returns></returns>
        public async Task<UploadUserPictureResultDto> UserPicture(IFormFile file)
        {
            var fileContent = ContentDispositionHeaderValue.Parse(file.ContentDisposition);

            var fileName = Path.GetFileName(fileContent.FileName.Trim()).ToString();

            var ext = Path.GetExtension(fileName);

            var dir = Path.Combine(_hostingEnvironment.WebRootPath, "UserPictures");

            var newFileName = Guid.NewGuid().ToString() + ext;

            if (!Directory.Exists(dir))
            {
                Directory.CreateDirectory(dir);
            }

            using (var fileStream = new FileStream(Path.Combine(dir, newFileName), FileMode.Create))
            {
                await file.CopyToAsync(fileStream);
            }

            return new UploadUserPictureResultDto {Uri = "UserPictures/" + newFileName};
        }
		/// <summary>
		/// 上传客户照片
		/// </summary>
		/// <param name="userPictureDto"></param>
		/// <returns></returns>
		public async Task<UploadUserPictureResultDto> UserPictureBase64(UploadUserPictureDto userPictureDto)
        {
            byte[] picBytes = Convert.FromBase64String(userPictureDto.PictureString);
			Stream stream = new MemoryStream(picBytes);
            Image image = Image.FromStream(stream);
            var dir = Path.Combine(_hostingEnvironment.WebRootPath, "UserPictures");

            var newFileName = Guid.NewGuid().ToString() + ".jpg";
			image.Save(Path.Combine(dir, newFileName), ImageFormat.Jpeg);

            return new UploadUserPictureResultDto { Uri = "UserPictures/" + newFileName };
		}

        /// <summary>
		/// 导出Customer为excel表,等待开发。
		/// </summary>
		/// <returns></returns>
		public async Task<FileDto> GetToExcel()
		{
			var customs = await _entityRepository.GetAll().ToListAsync();
			var customsListDtos = ObjectMapper.Map<List<CustomerListDto>>(customs);
			return _customListExcelExporter.ExportToExcel(customsListDtos); ;
		}

		/// <summary>
		/// 从Excel表导入数据
		/// </summary>
		/// <param name="file">文件</param>
		/// <param name="operation">有错误时，操作选择，默认提示报错，1表示替换该游客信息，2表是跳过该游客信息，</param>
		/// <returns></returns>
		[HttpPost]
		public async Task<AjaxResult> ImportCustomer(IFormFile file,string operation="0")
		{
			AjaxResult ajaxResult = new AjaxResult();
			var List = new List<CustomerListDto>();
			try
			{
				List<CustomExcelDto> data = _excelHelper.ReadToList<CustomExcelDto>(file);
				Guid branchId = GetBranchId().Result;
				foreach (var dto in data)
				{
					Customer temp = new Customer
					{
						CustomerName = dto.CustomerName,
						Mobile = dto.Mobile,
						Sex = dto.SexName=="男"? SexEnum.Man:SexEnum.Woman,
						CertificatesNum = dto.CertificatesNum,
						VerifiableType = getVerifiableTypeEnum(dto.CertificatesNum),
						CreationTime = DateTime.Now,
						CreatorUserId = AbpSession.UserId,
						BranchId = branchId,
						Id = Guid.NewGuid(),
					};
					Customer customer = await _entityManager.GetByIdentityNo(temp.CertificatesNum);
					if (customer != null)
					{
						if (customer.CustomerName != temp.CustomerName)
						{
							switch(operation)
							{
								case "0": {
										ajaxResult.Data = new List<Customer>() { temp };
										throw new UserFriendlyException("请确认用户名:" + temp.CustomerName + "和证件号:" + temp.CertificatesNum + "是否正确");
									}
								case "1": {
										customer.CustomerName = temp.CustomerName;
										customer.Mobile = temp.Mobile;
										customer.Sex = temp.Sex;
										customer = await _entityRepository.UpdateAsync(customer);
									} break;
								case "2": continue;
							}
						}
					}
					else
					{
						customer = await _entityRepository.InsertAsync(temp);
					}
					List.Add(customer.MapTo<CustomerListDto>());
				}
				ajaxResult.Data = List;
			}
			catch (Exception e)
			{
				//throw new UserFriendlyException(e.Message);
				ajaxResult.IsSuccess = false;
				ajaxResult.Message = e.Message;
			}
			return ajaxResult;
		}
		/// <summary>
		/// 批量插入游客信息
		/// </summary>
		/// <param name="customers">游客信息列表</param>
		/// <param name="operation">有错误时，操作选择，默认提示报错，1表示替换该游客信息，2表是跳过该游客信息，</param>
		/// <returns></returns>
		[HttpPost]
		public async Task<AjaxResult> BatchInsertCustomer(List<CustomerEditDto> customers, string operation = "0")
		{
			AjaxResult ajaxResult = new AjaxResult();
			var List = new List<CustomerListDto>();
			try
			{
				Guid branchId = GetBranchId().Result;
				foreach (var dto in customers)
				{
					Customer temp = new Customer
					{
						CustomerName = dto.CustomerName,
						Mobile = dto.Mobile,
						Sex = dto.Sex,
						CertificatesNum = dto.CertificatesNum,
						VerifiableType = getVerifiableTypeEnum(dto.CertificatesNum),
						CreationTime = DateTime.Now,
						CreatorUserId = AbpSession.UserId,
						BranchId = branchId,
						Id = Guid.NewGuid(),
					};
					Customer customer = await _entityManager.GetByIdentityNo(temp.CertificatesNum);
					if (customer != null)
					{
						if (customer.CustomerName != temp.CustomerName)
						{
							switch (operation)
							{
								case "0":
									{
										ajaxResult.Data = new List<Customer>() { temp };
										throw new UserFriendlyException("请确认用户名:" + temp.CustomerName + "和证件号:" + temp.CertificatesNum + "是否正确");
									}
								case "1":
									{
										customer.CustomerName = temp.CustomerName;
										customer.Mobile = temp.Mobile;
										customer.Sex = temp.Sex;
										customer = await _entityRepository.UpdateAsync(customer);
									}
									break;
								case "2": continue;
							}
						}
					}
					else
					{
						customer = await _entityRepository.InsertAsync(temp);
					}
					List.Add(customer.MapTo<CustomerListDto>());
				}
				ajaxResult.Data = List;
			}
			catch (Exception e)
			{
				//throw new UserFriendlyException(e.Message);
				ajaxResult.IsSuccess = false;
				ajaxResult.Message = e.Message;
			}
			return ajaxResult;

		}

		///<summary>
		///官网注册
		/// </summary>
		[AbpAllowAnonymous]
		public async Task CreateUserAsync(CreateOrUpdateCustomerInput input)
		{
			var custom = ObjectMapper.Map<Customer>(input.Customer); //Passwords is not mapped (see mapping configuration)
			var a = _entityRepository.GetAll().Where(i=>i.CustomerName==input.Customer.CustomerName).Count();
			if (a > 0) {
				throw new UserFriendlyException("用户名已存在,请重新输入");
			}
			    //Set password
				if (!(bool)input.SetRandomPassword && !input.Customer.LoginPwd.IsNullOrEmpty())
				{
					input.Customer.LoginPwd = Customer.CreateRandomPassword();
				}
				else
				{
					await _customerManager.GetPwdConfirmationCode(input.Customer.LoginPwd);
				}
				//custom.LoginPwd = _passwordHasher.HashPassword(custom, input.Customer.LoginPwd);
				await CreateOrUpdate(input);
		}
		/// <summary>
		/// 通过指定Openid获取CustomerListDto信息
		/// </summary>
		public async Task<CustomerListDto> GetByOpenId(string OpenId)
		{
			var entity = await _entityRepository.FirstOrDefaultAsync(m => m.OpenID == OpenId);

			return entity.MapTo<CustomerListDto>();
		}
		#region 私有方法
		VerifiableTypeEnum getVerifiableTypeEnum(string VerifiableTypeName)
		{
			var result = VerifiableTypeEnum.IdentityCard;
			switch (VerifiableTypeName)
			{
				case "身份证": break;
				case "港澳回乡证": result = VerifiableTypeEnum.ReturnCard; break;
				case "台胞证": result = VerifiableTypeEnum.TaiwanCard; break;
			}
			return result;
		}
		#endregion
	}
}


